package com.zpark.uaa.service.config;

import com.zpark.uaa.service.integration.IntegrationUserDetailsAuthenticationHandler;
import com.zpark.uaa.service.integration.IntegrationUserDetailsAuthenticationProvider;
import com.zpark.user.api.service.IAuthorizationService;
import com.zpark.user.api.service.ITenantService;
import com.zpark.user.service.service.TenantServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;

/**
 * Spring Security配置
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private ITenantService tenantService;
	@Autowired
	private IAuthorizationService authorizationService;

	public SecurityConfig() {
	}

	/**
	 * 创建并配置一个IntegrationUserDetailsAuthenticationHandler实例。
	 * 这个处理器用于处理基于用户详细信息的认证请求。
	 *
	 * @return IntegrationUserDetailsAuthenticationHandler 一个配置好的认证处理器实例。
	 */
	@Bean
	public IntegrationUserDetailsAuthenticationHandler
			integrationUserDetailsAuthenticationHandler(){
		System.err.println("创建并配置一个IntegrationUserDetailsAuthenticationHandler实例");
	    // 创建一个新的IntegrationUserDetailsAuthenticationHandler实例
	    IntegrationUserDetailsAuthenticationHandler authenticationHandler =
				new IntegrationUserDetailsAuthenticationHandler();
	    // 为认证处理器设置租户服务
	    authenticationHandler.setTenantService(tenantService);
	    return authenticationHandler;
	}

	/**
	 * 创建并配置一个IntegrationUserDetailsAuthenticationProvider实例。
	 * 这个方法不接受任何参数，它主要用于初始化并配置AuthenticationProvider，
	 * 特别是为集成细节认证处理提供支持。
	 *
	 * @return IntegrationUserDetailsAuthenticationProvider 一个配置好的认证提供者实例，
	 *         用于处理基于集成用户详情的认证请求。
	 */
	@Bean
	public IntegrationUserDetailsAuthenticationProvider
				integrationUserDetailsAuthenticationProvider(){
		System.err.println("创建并配置一个IntegrationUserDetailsAuthenticationProvider实例");
	    // 创建一个新的IntegrationUserDetailsAuthenticationProvider实例，
	    // 并将其与之前配置的integrationUserDetailsAuthenticationHandler关联。
	    IntegrationUserDetailsAuthenticationProvider provider =
				new IntegrationUserDetailsAuthenticationProvider(
						integrationUserDetailsAuthenticationHandler());
	    return provider;
	}


	/**
	 * 配置AuthenticationManagerBuilder以使用自定义的认证提供者。
	 * 这个方法覆盖了父类的configure方法，专门用于设置认证管理器的构建器。
	 *
	 * @param auth AuthenticationManagerBuilder的实例，用于构建认证管理器。
	 * @throws Exception 如果在配置过程中发生任何错误，则抛出异常。
	 */
	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		System.err.println("配置AuthenticationManagerBuilder以使用自定义的认证提供者");
	    // 将自定义的用户详情认证提供者注册到认证管理器构建器中
	    auth.authenticationProvider(integrationUserDetailsAuthenticationProvider());
	}


	//不定义没有password grant_type
	/**
	 * 创建并返回一个AuthenticationManager实例。
	 * 这个方法是覆盖了Spring Security提供的默认实现，通过调用父类的同名方法来获取AuthenticationManager实例。
	 *
	 * @return AuthenticationManager 用于进行用户认证的管理器实例
	 * @throws Exception 如果创建过程中遇到任何问题，则抛出异常
	 */
	@Override
	@Bean
	public AuthenticationManager authenticationManagerBean() throws Exception {
		System.err.println("创建并返回一个AuthenticationManager实例。");
		return super.authenticationManagerBean();
	}

	/**
	 * 配置Web安全设置，决定哪些请求应该被忽略不进行安全验证。
	 * @param web 用于配置Web安全性的对象
	 * @throws Exception 如果配置过程中发生错误，则可能抛出异常
	 */
	@Override
	public void configure(WebSecurity web) throws Exception {
		System.out.println("配置Web安全设置，决定哪些请求应该被忽略不进行安全验证。");
	    // 忽略对特定路径的请求进行安全验证
	    web.ignoring()
				.antMatchers(
						"/public/**",
						"/webjars/**",
						"/v2/**",
						"/swagger**",
						"/static/**",
						"/resources/**");
	    // 注释掉的代码用于配置HttpFirewall，严格控制请求的HTTP方法和头部信息等
	    //web.httpFirewall(new DefaultHttpFirewall());//StrictHttpFirewall 去除验url非法验证防火墙
	}

	/**
	 * 配置HTTP安全设置，定义应用程序的访问权限和安全特性。
	 *
	 * @param http 用于配置HttpSecurity的接口，可定制应用程序的访问控制、登录、登出、CSRF保护等安全设置。
	 * @throws Exception 如果在配置过程中发生错误，则抛出异常。
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		System.err.println("配置HTTP安全设置，定义应用程序的访问权限和安全特性。");
	    http.authorizeRequests() // 配置请求授权
	            .antMatchers("/login*").permitAll() // 允许所有用户访问登录页面及其相关资源
	            .antMatchers("/logout*").permitAll() // 允许所有用户执行登出操作
	            .antMatchers("/druid/**").permitAll() // 允许所有用户访问druid监控页面
				.antMatchers("/uaa/oauth/**").permitAll()
	            .anyRequest().authenticated() // 要求用户认证通过后才能访问其他所有资源
	            .and().formLogin() // 配置表单登录
	            .loginPage("/login") // 指定登录页面
	            .loginProcessingUrl("/login.do") // 指定处理登录请求的URL
	            .failureUrl("/login?authentication_error=1") // 登录失败跳转的页面
	            .defaultSuccessUrl("/oauth/authorize") // 登录成功后跳转的默认页面
	            .usernameParameter("username") // 指定登录表单中的用户名参数
	            .passwordParameter("password") // 指定登录表单中的密码参数
	            .and().logout() // 配置登出功能
	            .logoutUrl("/logout.do") // 指定登出请求的URL
	            .deleteCookies("JSESSIONID") // 登出时删除会话cookie
	            .logoutSuccessUrl("/") // 登出成功后跳转的页面
	            .and().csrf().disable() // 禁用跨站请求伪造(CSRF)保护
	            .exceptionHandling() // 配置异常处理
	            .accessDeniedPage("/login?authorization_error=2"); // 访问权限拒绝时跳转的页面
	}
}

